//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Mapping Application Block
//===============================================================================

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Drawing.Design;
using EntLibContrib.Mapping.Properties;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design.Validation;

namespace EntLibContrib.Mapping.Configuration.Design
{
	/// <summary>
	/// Represents a custom mapper that consists of key value pairs. 
	/// </summary>
	public class CustomMapperNode : MapperBaseNode
	{
		#region Fields
		private List<EditableKeyValue> editableAttributes = new List<EditableKeyValue>();
		private string typeName;
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the attributes for the custom mapper.
		/// </summary>
		/// <value>
		/// The attributes for the custom mapper.
		/// </value>		
		[SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
		[CustomAttributesValidation]
		[MappingCategory("CategoryProvider")]
		[MappingDescription("CustomMapperExtensionsDescription")]
		public List<EditableKeyValue> Attributes
		{
			get
			{
				return editableAttributes;
			}
		}

		/// <summary>
		/// Gets or sets the <see cref="Type"/> that implements <see cref="IMapper"/>.
		/// </summary>
		/// <value>
		/// The <see cref="Type"/> that implements <see cref="IMapper"/>.
		/// </value>
		[Required]
		[Editor(typeof(TypeSelectorEditor), typeof(UITypeEditor))]
		[BaseType(typeof(IMapper), typeof(CustomMapperData))]
		[MappingCategory("CategoryProvider")]
		[MappingDescription("CustomMapperNodeTypeDescription")]
		public string TypeName
		{
			get { return typeName; }
			set { typeName = value; }
		}

		/// <summary>
		/// Gets a <see cref="CustomMapperData"/> configuration object using the node data.
		/// </summary>
		/// <value>
		/// A <see cref="CustomMapperData"/> configuration object using the node data.
		/// </value>
		[ReadOnly(true)]
		public override MapperBaseData MapperData
		{
			get
			{
				CustomMapperData customData = new CustomMapperData(Name, typeName);
				customData.Attributes.Clear();
				foreach (EditableKeyValue keyValue in editableAttributes)
				{
					customData.Attributes.Add(keyValue.Key, keyValue.Value);
				}
				return customData;
			}
		}
		#endregion

		#region Construction
		/// <summary>
		/// Initialize a new instance of the <see cref="CustomMapperNode"/> class.
		/// </summary>
		public CustomMapperNode()
			: this(new CustomMapperData(InternalResources.DefaultCustomMapperNodeName, string.Empty))
		{
		}

		/// <summary>
		/// Initialize a new instance of the <see cref="CustomMapperNode"/> class with a <see cref="CustomMapperData"/> object.
		/// </summary>
		/// <param name="customMapperData">The <see cref="CustomMapperData"/> to display.</param>
		public CustomMapperNode(CustomMapperData customMapperData)
		{
			if (null == customMapperData) throw new ArgumentNullException("customMapperData");

			Rename(customMapperData.Name);
			foreach (string key in customMapperData.Attributes)
			{
				editableAttributes.Add(new EditableKeyValue(key, customMapperData.Attributes[key]));
			}
			this.typeName = customMapperData.TypeName;
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Clones this instance.
		/// </summary>
		/// <returns></returns>
		public override MapperBaseNode Clone()
		{
			CustomMapperNode mapperNode = new CustomMapperNode((CustomMapperData)this.MapperData);
			foreach (ConfigurationNode mapNode in this.Nodes)
			{
				MapBaseNode node = mapNode as MapBaseNode;
				if (node != null)
				{
					MapBaseNode newMapNode = node.Clone();
					mapperNode.AddNode(newMapNode);
				}
			}
			return mapperNode;
		}
		#endregion
	}
}